package com.gobang.demo.game;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gobang.demo.model.MatchResponse;
import com.gobang.demo.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;


@Component
@Slf4j
// 这个类表示 "匹配器", 通过这个类负责完成整个匹配功能
public class Mather {
    // 根据玩家积分划分出3个匹配队列
    private Queue<User> normalQueue = new LinkedList<>();
    private Queue<User> highQueue = new LinkedList<>();
    private Queue<User> veryHighQueue = new LinkedList<>();
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RoomManager roomManager;

    // 把玩家放到匹配队列中
    public void add(User user) {
        if (user.getScore() < 2000) {
            // 由于存在多个线程的用户同时匹配，存在线程安全问题,所以要加锁
            synchronized (normalQueue) {
                normalQueue.offer(user);
                // 有用户加入匹配就通知 wait()
                normalQueue.notify();
            }
            log.info("玩家{}进入普通队列",user.getUserName());
        }else if (user.getScore() >= 2000 && user.getScore() < 3000) {
            synchronized(highQueue) {
                highQueue.offer(user);
                highQueue.notify();
            }
            log.info("玩家{}进入高级队列",user.getUserName());
        }else {
            synchronized (veryHighQueue) {
                veryHighQueue.offer(user);
                veryHighQueue.notify();
            }
            log.info("玩家{}进入超高级队列",user.getUserName());
        }
    }

    public void remove(User user) {
        if (user.getScore() < 2000) {
            synchronized (normalQueue) {
                normalQueue.remove(user);
            }
            log.info("玩家{}离开普通队列",user.getUserName());
        }else if (user.getScore() >= 2000 && user.getScore() < 3000) {
           synchronized (highQueue) {
               highQueue.remove(user);
           }
            log.info("玩家{}离开高级队列",user.getUserName());
        }else {
            synchronized (veryHighQueue) {
                veryHighQueue.remove(user);
            }
            log.info("玩家{}离开超高级队列",user.getUserName());
        }
    }

    public Mather() {
        // 创建三个线程, 分别针对这三个匹配队列, 进行操作.
        Thread t1 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(normalQueue);

                }
            }
        };
        t1.start();
        Thread t2 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(highQueue);
                }
            }
        };
        t2.start();
        Thread t3 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(veryHighQueue);
                }
            }
        };
        t3.start();
    }


    private void handlerMatch(Queue<User> matchQueue) {
       synchronized (matchQueue) {
           try {
               //    检测队列中元素个数是否达到 2
               //    队列的初始情况可能是 空
               //    如果往队列中添加一个元素, 这个时候, 仍然是不能进行后续匹配操作的.
               //    因此在这里使用 while 循环检查是更合理的
               while (matchQueue.size() < 2) {
                   matchQueue.wait();
               }
               // 尝试从队列中取出两个玩家
               User player1 = matchQueue.poll();
               User player2 = matchQueue.poll();
               log.info("玩家{} 与 玩家{} 匹配成功",player1.getUserName(),player2.getUserName());
               WebSocketSession player1Session = onlineUserManager.getFromGameHall(player1.getUserId());
               WebSocketSession player2Session = onlineUserManager.getFromGameHall(player2.getUserId());
               if (player1Session == null) {
                   // 如果玩家1 现在不在线了, 就把玩家2 重新放回到匹配队列中
                   matchQueue.offer(player2);
                   return;
               }
               if (player2Session == null) {
                   // 如果玩家2 现在不在线了, 就把玩家1 重新放回到匹配队列中
                   matchQueue.offer(player1);
                   return;
               }
               if (player1Session == player2Session) {
                   matchQueue.offer(player1);
                   return;
               }
               //把玩家加入房间
               Room room = new Room();
               roomManager.add(room,player1.getUserId(),player2.getUserId());

               // 给玩家反馈信息: 你匹配到对手了~
               MatchResponse response = new MatchResponse();
               response.setOk(true);
               response.setMessage("matchSuccess");
               player1Session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
               player2Session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
           }catch (IOException e) {
               e.printStackTrace();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }

    }
}
